package NetWork;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 故我
 * Date: 2023-10-21
 * Time: 9:38
 */
public class TcpEchoServer {
    private ServerSocket listensocket = null;

    public TcpEchoServer(int port) throws IOException {
        listensocket = new ServerSocket(port);
    }

    //启动服务器，这个套接字负责去接收新的客户端连接套接字
    public void Start() throws IOException {
        System.out.println("TCP服务器启动!");
        //改为线程池版本，因为线程的数量不是固定的 不能使用那个fix 使用 cache
        ExecutorService pool = Executors.newCachedThreadPool();
        while (true) {
            Socket newsocket = listensocket.accept();
            //此时是一个单线程版的服务器，一次只能处理一个连接，这里采用多线程版本进行处理多个连接
//            Thread t = new Thread(()->{
//                try {
//                    process(newsocket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            t.start();

            pool.submit(()->{
                try {
                    process(newsocket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    public void process(Socket newsocket) throws IOException {
        System.out.printf("客户端上线：[%s:%d]\n", newsocket.getInetAddress().toString(), newsocket.getPort());
        //使用流操作对套接字接口进行读取操作
        try (InputStream inputStream = newsocket.getInputStream();
             OutputStream outputStream = newsocket.getOutputStream()) {
            while (true) {
                Scanner scanner = new Scanner(inputStream);//从inputStream中获取数据
                if (!scanner.hasNext()) {
                    //此时已经没有数据可读了，代表客户端退出
                    System.out.printf("客户端退出了：[%s:%d]\n", newsocket.getInetAddress().toString(), newsocket.getPort());
                    break;
                }
                String recvStr = scanner.next();//读到空格或者换行就结束读取
                String respStr = functor(recvStr);
                //对数据进行发送，以字符串的风格
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(respStr);//这里会自动加上一个 \n 换行，如果不加，客户端那边会一直读取，导致一直阻塞接收
                printWriter.flush();
                System.out.printf("[%s:%d] recv: %s  resp: %s\n",
                        newsocket.getInetAddress().toString(), newsocket.getPort(), recvStr, respStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //可能连接是长连接，长时间不通信，需要关闭套接字
            newsocket.close();
        }
    }

    public String functor(String recvStr) {
        return recvStr;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(8080);
        server.Start();
    }
}
